package com.ccepc.algmanage.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ccepc.algmanage.mapper.IdentificationRecordMapper;
import com.ccepc.algmanage.service.*;
import com.ccepc.algmanage.utils.AuthInfoUtils;
import com.ccepc.algmanage.utils.CommonUtils;
import com.ccepc.algmanage.utils.HkUtils;
import com.ccepc.common.core.util.R;
import com.ccepc.demo.api.dto.IdentificationRecordDto;
import com.ccepc.demo.api.entity.*;
import com.obs.services.ObsClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.List;

/**
 *
 *
 * @author pigx code generator
 * @date 2023-11-16 09:18:26
 */
@Service
@Slf4j
public class IdentificationRecordServiceImpl extends ServiceImpl<IdentificationRecordMapper, IdentificationRecord> implements IdentificationRecordService {

    @Resource
    private AlgorithmInfoService algorithmInfoService;

    @Resource
    private LinkedDeviceService linkedDeviceService;

    @Resource
    private ObsService obsService;

    @Resource
    private PlcConfigService plcConfigService;

    @Resource
    private AlgorithmConfigService algorithmConfigService;

    @Resource
    private DeployInfoService deployInfoService;

    @Override
    public Object pageWithDateRage(IdentificationRecordDto identificationRecordDto) {
        Page<IdentificationRecord> page = new Page<>(identificationRecordDto.getCurrent(), identificationRecordDto.getSize());
        LambdaQueryWrapper<IdentificationRecord> queryWrapper = new LambdaQueryWrapper<>();
        if (identificationRecordDto.getDateBegin() != null) {
            LocalDateTime dateBegin = LocalDateTime.parse(identificationRecordDto.getDateBegin());
            LocalDateTime dateEnd = LocalDateTime.parse(identificationRecordDto.getDateEnd());
            queryWrapper.between(IdentificationRecord::getCreatedTime, dateBegin, dateEnd);
        }
        IdentificationRecord identificationRecord = identificationRecordDto.getIdentificationRecord();
        queryWrapper
                .like(identificationRecord.getDeviceNo() != null && !identificationRecord.getDeviceNo().isEmpty(),
                        IdentificationRecord::getDeviceNo, identificationRecord.getDeviceNo())
                .eq(identificationRecord.getAlgorimId() != null,
                        IdentificationRecord::getAlgorimId, identificationRecord.getAlgorimId())
                .eq(identificationRecord.getAnalysisType() != null,
                        IdentificationRecord::getAnalysisType, identificationRecord.getAnalysisType())
                .eq(identificationRecord.getIsHandle() != null,
                        IdentificationRecord::getIsHandle, identificationRecord.getIsHandle())
                .eq(IdentificationRecord::getTenantId, AuthInfoUtils.getTenantId())
                .orderByDesc(IdentificationRecord::getCreatedTime);
        if (identificationRecordDto.getIsLinkRecord() == 1) {
            queryWrapper.isNotNull(IdentificationRecord::getLinkedIds);
        }
        return this.page(page, queryWrapper);
    }


    @Transactional
    @Override
    public ResponseEntity<Object> saveHkRecords(String request, ObsClient obsClient, String bucketName){
        // 解析request串
        IdentificationRecord identificationRecord = HkUtils.parseSubscriptionInfo(request);
        if (identificationRecord != null) {
            if (identificationRecord.getIdenResults() == null) {
                return ResponseEntity.ok("图片格式不对");
            }
            // 上传图片到华为云
            String deviceNo = identificationRecord.getDeviceNo();
            String fileName = System.currentTimeMillis() + "_" + deviceNo + ".jpg";
            if (obsService.uploadAndShowImg(obsClient, bucketName, fileName, identificationRecord.getIdenResults()) != null) {
                identificationRecord.setIdenResults(fileName);
            }
            // 赋值算法相关信息
            AlgorithmInfo algorithmInfo = algorithmInfoService.getOne(
                    new LambdaQueryWrapper<AlgorithmInfo>()
                            .like(AlgorithmInfo::getEventCode, identificationRecord.getEventCode())
            );
            identificationRecord.setAlgorimId(algorithmInfo.getId());
            identificationRecord.setAnalysisType(algorithmInfo.getAlgTypeId());
            identificationRecord.setTenantId(algorithmInfo.getTenantId());
            // 查询是否存在联动设备
            LinkedDevice linkedDevice = linkedDeviceService.getOne(
                    new LambdaQueryWrapper<LinkedDevice>()
                            .eq(deviceNo != null, LinkedDevice::getDeviceNo, deviceNo)
            );
            if (linkedDevice == null) {
                return ResponseEntity.ok(this.save(identificationRecord));
            } else {
                identificationRecord.setLinkedIds(linkedDevice.getLinkedIds());
                this.save(identificationRecord);
                // 向联动设备发送联动请求
                return ResponseEntity.ok(linkedDeviceService.sendMessage(linkedDevice, identificationRecord));
            }
        }
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
    }

    @Override
    public Object saveAlgRecords(String request, ObsClient obsClient, String bucketName) {
        JSONObject jsonObject = CommonUtils.stringToJson(request);
        IdentificationRecord identificationRecord = new IdentificationRecord();
        String deviceNo = jsonObject.getString("cameraIndexCode");
        identificationRecord.setDeviceNo(deviceNo);
        String eventCode = jsonObject.getString("eventCode");
        if (eventCode != null) {
            identificationRecord.setEventCode(eventCode);
            AlgorithmInfo algorithmInfo = algorithmInfoService.getOne(
                    new LambdaQueryWrapper<AlgorithmInfo>()
                            .eq(AlgorithmInfo::getEventCode, eventCode)
            );
            if (algorithmInfo!=null) {
                identificationRecord.setAlgorimId(algorithmInfo.getId());
                identificationRecord.setAnalysisType(algorithmInfo.getAlgTypeId());
                identificationRecord.setEventName(algorithmInfo.getAlgName());
                identificationRecord.setTenantId(algorithmInfo.getTenantId());
            }
        } else {
            return R.failed("eventCode cannot be null");
        }
        identificationRecord.setIsPush(0);
        identificationRecord.setIsHandle(0);

        // 获取图片地址并上传至华为云
        AlgorithmConfig algorithmConfig = algorithmConfigService.getOne(new LambdaQueryWrapper<AlgorithmConfig>()
                .like(AlgorithmConfig::getCameraIds, identificationRecord.getDeviceNo()));
        DeployInfo deployInfo = deployInfoService.getById(algorithmConfig.getDeployId());
        String picUrl = "http://" + deployInfo.getInterfaceAddr() + jsonObject.getString("identifyImg");
        String fileName = System.currentTimeMillis() + "_" + deviceNo + ".jpg";
        if (obsService.uploadAndShowImg(obsClient, bucketName, fileName, picUrl) != null) {
            identificationRecord.setIdenResults(fileName);
        }

        identificationRecord.setCreatedTime(LocalDateTime.parse(jsonObject.getString("createdTime")));

        return R.ok(this.save(identificationRecord));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResponseEntity<Object> removeRecord(Integer id, ObsClient obsClient, String bucketName) {
        String idenResults = this.getById(id).getIdenResults();
        if (this.removeById(id)) {
            // 删除华为云图片
            return obsService.deleteImage(idenResults, obsClient, bucketName);
        }
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
    }

    @Override
    public R saveVideo(LinkVideo linkVideo) {
        try {
            LocalDateTime recordTime = LocalDateTime.parse(linkVideo.getRecordTime().substring(0, 19));
            List<IdentificationRecord> records = this.list(
                    new LambdaQueryWrapper<IdentificationRecord>()
                            .eq(IdentificationRecord::getDeviceNo, linkVideo.getCameraIndexCode())
                            .isNotNull(IdentificationRecord::getLinkedIds)
                            .orderByAsc(IdentificationRecord::getCreatedTime)
            );
            IdentificationRecord closestRecord = null;
            long minDifference = Long.MAX_VALUE;
            for (IdentificationRecord record : records) {
                long difference = Math.abs(Duration.between(record.getCreatedTime(), recordTime).getSeconds());
                if (difference < minDifference) {
                    minDifference = difference;
                    closestRecord = record;
                }
            }
            if (closestRecord != null) {
                closestRecord.setLinkedVideo("http://121.36.109.248:81/" + linkVideo.getVideoUrl());
                if (this.updateById(closestRecord)) {
                    String[] linkedIds = closestRecord.getLinkedIds().split(",");
                    // 关闭联动设备
                    for (String linkedId : linkedIds) {
                        plcConfigService.changeStatus(linkedId, "false", false);
                    }
                }
                return R.ok();
            } else {
                return R.failed("未查询到相关联动记录");
            }
        } catch (DateTimeParseException e) {
            return R.failed("日期格式错误，请按照LocalDateTime(2023-11-22T17:24:25)格式发送");
        }

    }

    @Transactional
    @Override
    public R updateRemark(List<IdentificationRecord> identificationRecords) {
        identificationRecords.forEach(
                identificationRecord -> {
                    this.update(
                            new LambdaUpdateWrapper<IdentificationRecord>()
                                    .eq(IdentificationRecord::getId, identificationRecord.getId())
                                    .set(IdentificationRecord::getIdenAdvice, identificationRecord.getIdenAdvice())
                                    .set(IdentificationRecord::getIsHandle, identificationRecord.getIsHandle())
                                    .set(IdentificationRecord::getHandleTime, LocalDateTime.now())
                                    .set(IdentificationRecord::getHandleBy, identificationRecord.getHandleBy()
                                    )
                    );
                }
        );
        return R.ok();
    }

    @Override
    @Transactional
    public ResponseEntity<Object> removeBatch(List<IdentificationRecord> records, ObsClient obsClient, String bucketName) {
        records.forEach(record -> {
            String idenResults = this.getById(record.getId()).getIdenResults();
            this.removeById(record.getId());
            try {
                obsService.deleteImage(idenResults, obsClient, bucketName);
            } catch (Exception e) {
                log.error(e.getMessage());
            }
        });
        return ResponseEntity.ok("0");
    }

}
